package com.bestcem.xm.survey.grpc.client;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.bestcem.xm.common.core.constant.Constants;
import com.bestcem.xm.common.core.constant.GrpcClientNames;
import com.bestcem.xm.qdes.grpc.v1.services.*;
import com.bestcem.xm.survey.convert.grpc.SurveyGrpcConvertMapper;
import com.bestcem.xm.survey.grpc.client.dto.QdesNameListDto;
import com.bestcem.xm.survey.grpc.client.dto.QdesQuestionDto;
import com.bestcem.xm.survey.grpc.client.dto.QstructsDto;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Component
public class QdesGrpcClient {

    @GrpcClient(GrpcClientNames.DS_QDES)
    private BaseQdesServiceGrpc.BaseQdesServiceBlockingStub baseQdesServiceBlockingStub;

    @GrpcClient(GrpcClientNames.DS_QDES)
    private BpProjectServiceGrpc.BpProjectServiceBlockingStub bpProjectServiceBlockingStub;

    private final SurveyGrpcConvertMapper grpcConvertMapper;

    public QdesGrpcClient(SurveyGrpcConvertMapper grpcConvertMapper) {
        this.grpcConvertMapper = grpcConvertMapper;
    }


    public Project getProject(String id) {
        if (StrUtil.isBlank(id)) {
            log.error("[Survey] getProject, id 不能为空");
            return null;
        }
        GetProjectRequest.Builder builder = GetProjectRequest.newBuilder();
        builder.setId(id);
        try {
            ProjectResponse response = baseQdesServiceBlockingStub.getProject(builder.build());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[Survey] getProject, id = {} Error; ErrorMsg: {}", id, response);
                return null;
            }
            return response.getProject();
        } catch (Exception e) {
            log.error("[Survey] exp getProject, id = {} Error", id, e);
            return null;
        }
    }

    public List<Quota> getQuotaList(String projectId, Integer quotaType) {
        ListQuotaRequest.Builder builder = ListQuotaRequest.newBuilder();
        Quota quota;
        if (quotaType != null) {
            QuotaQuotaType quotaQuotaType = QuotaQuotaType.forNumber(quotaType);
            quota = Quota.newBuilder().setProjectId(projectId).setQuotaType(quotaQuotaType).build();
            builder.setQuota(quota);
            QuotaSearchResponse response = baseQdesServiceBlockingStub.listQuota(builder.build());
            if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
                log.error("[Survey] getQuotaList failed, response: {}", response);
                return null;
            }
            return response.getQuotaListList();
        } else {
            quota = Quota.newBuilder().setProjectId(projectId).setQuotaType(QuotaQuotaType.QUOTA_QUOTA_TYPE_NORMAL).build();
            builder.setQuota(quota);
            QuotaSearchResponse response = baseQdesServiceBlockingStub.listQuota(builder.build());
            if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
                log.error("[Survey] getQuotaList failed, response: {}", response);
                return null;
            }
            List<Quota> quotas = new ArrayList<>(response.getQuotaListList());
            quota = Quota.newBuilder().setProjectId(projectId).setQuotaType(QuotaQuotaType.QUOTA_QUOTA_TYPE_CROSS).build();
            builder.setQuota(quota);
            QuotaSearchResponse responseCross = baseQdesServiceBlockingStub.listQuota(builder.build());
            if (responseCross.getStatus().getCodeValue() != Constants.SUCCESS) {
                log.error("[Survey] getQuotaList failed, response: {}", responseCross);
                return null;
            }
            quotas.addAll(responseCross.getQuotaListList());
            return quotas;
        }
    }

    public QStruct getQStruct(String id) {
        GetQStructRequest request = GetQStructRequest.newBuilder().setId(id).build();
        QStructResponse response = baseQdesServiceBlockingStub.getQStruct(request);
        if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
            log.error("[Survey] listProject failed, response: {}", response);
            return null;
        }
        return response.getQStruct();
    }

    public List<Question> getQuestionList(String structId) {
        ListQuestionRequest.Builder builder = ListQuestionRequest.newBuilder();
        Question question = Question.newBuilder().setStructId(structId).build();
        builder.setQuestion(question);
        QuestionSearchResponse response = baseQdesServiceBlockingStub.listQuestion(builder.build());
        if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
            log.error("[Survey] getQuestionList failed, response: {}", response);
            return null;
        }
        return response.getQuestionListList();
    }

    public void updateQuota(String quotaId, Quota quota) {
        UpdateQuotaRequest.Builder builder = UpdateQuotaRequest.newBuilder();
        builder.setId(quotaId);
        builder.setQuota(quota);
        UpdateResponse response = baseQdesServiceBlockingStub.updateQuota(builder.build());
        if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
            log.error("[Survey] updateQuota failed, response: {}", response);
        }
    }

    public Quota getQuota(String quotaId) {
        if (StringUtils.isEmpty(quotaId)) {
            return null;
        }
        GetQuotaRequest.Builder builder = GetQuotaRequest.newBuilder();
        builder.setId(quotaId);
        QuotaResponse response = baseQdesServiceBlockingStub.getQuota(builder.build());
        if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
            log.error("[Survey] getQuota failed, response: {}", response);
            return null;
        }
        return response.getQuota();
    }

    public QdesProject getCurrentProject(String id) {
        GetCurrentProjectRequest.Builder builder = GetCurrentProjectRequest.newBuilder();
        builder.setProjectId(id);
        try {
            GetCurrentProjectResponse response = bpProjectServiceBlockingStub.getCurrentProject(builder.build());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[Survey] getCurrentProject, id = {}, Error; ErrorMsg: {}", id, response);
                return null;
            }
            return response.getProject();
        } catch (Exception e) {
            log.error("[Survey] exp getCurrentProject id = {}, Error;", id, e);
            return null;
        }
    }

    public QdesProject getReleasedProject(String id, Integer version) {
        GetReleasedProjectRequest.Builder builder = GetReleasedProjectRequest.newBuilder();
        builder.setProjectId(id);
        builder.setVersion(version);
        try {
            GetReleasedProjectResponse response = bpProjectServiceBlockingStub.getReleasedProject(builder.build());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[Survey] getReleasedProject, id = {},version = {} Error; ErrorMsg: {}", id, version, response);
                return null;
            }
            return response.getProject();
        } catch (Exception e) {
            log.error("[Survey] exp getReleasedProject id = {},version = {} Error;", id, version, e);
            return null;
        }
    }

    public void finishProject(String project_id) throws Exception {
        FinishProjectRequest.Builder builder = FinishProjectRequest.newBuilder();
        builder.setProjectId(project_id);
        FinishProjectResponse response = bpProjectServiceBlockingStub.finishProject(builder.build());
        if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
            log.error("[Survey] finishProject, project_id = {} Error; ErrorMsg: {}", project_id, response);
            throw new Exception("finishProject error");
        }
    }

    public List<Integer> getQlistWithProjectId(String project_id, boolean is_preview) {
        GetQlistWithProjectIdRequest.Builder builder = GetQlistWithProjectIdRequest.newBuilder();
        builder.setProjectId(project_id);
        builder.setIsPreview(is_preview);
        try {
            GetQlistWithProjectIdResponse response = bpProjectServiceBlockingStub.getQlistWithProjectId(builder.build());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[Survey] getQlistWithProjectId, project_id = {},is_preview = {} Error; ErrorMsg: {}", project_id, is_preview, response);
                return null;
            }
            List<Integer> qIdsList = new ArrayList<>();
            for (int i = 0; i < response.getQIdsCount(); i++) {
                qIdsList.add(response.getQIds(i));
            }
            return qIdsList;
        } catch (Exception e) {
            log.error("[Survey] exp getQlistWithProjectId project_id = {},is_preview = {} Error;", project_id, is_preview, e);
            return null;
        }
    }

    public List<QdesQuestionDto> getReleasedProjectQuestions(String projectId, Integer version, Boolean surveyOrder) {
        GetReleasedProjectQuestionsRequest.Builder builder = GetReleasedProjectQuestionsRequest.newBuilder();
        if (StrUtil.isNotBlank(projectId)) {
            builder.setPid(projectId);
        }
        if (version != null) {
            builder.setVersion(version);
        }
        if (surveyOrder != null) {
            builder.setSurveyOrder(surveyOrder);
        }

        // 获取已发布的问题
        GetReleasedProjectQuestionsResponse response = bpProjectServiceBlockingStub.getReleasedProjectQuestions(builder.build());
        if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
            log.error("[Survey] getReleasedProjectQuestions, projectId: {}, version: {}, surveyOrder: {}, response: {}", projectId, version, surveyOrder, response);
            return null;
        }

        // 返回结果
        List<QuestionInfoList> questions = response.getQuestionsList();
        return questions.stream().map(this::toQdesQuestionDto).filter(Objects::nonNull).collect(Collectors.toList());
    }

    private QdesQuestionDto toQdesQuestionDto(QuestionInfoList question) {
        if (question == null) {
            return null;
        }

        QdesQuestionDto questionDto = new QdesQuestionDto();
        questionDto.setId(question.getId());
        questionDto.setType(question.getType());
        questionDto.setGid(question.getGid());
        questionDto.setTitle(question.getTitle());
        questionDto.setCustomQtype(question.getCustomQtype());
        questionDto.setCid(question.getCid());
        questionDto.setCurrentTemplate(question.getCurrentTemplate());

        List<String> tags = new ArrayList<>();
        question.getTagListList().forEach(it -> tags.addAll(ListUtil.of(it.split("\\n"))));
        questionDto.setTags(tags);

        List<QdesQuestionDto.QdesQuestionOptionDto> items = question.getItemsList().stream().map(this::toQdesQuestionOptionDto).filter(Objects::nonNull).collect(Collectors.toList());
        List<QdesQuestionDto.QdesQuestionOptionDto> rowItems = question.getRowItemsList().stream().map(this::toQdesQuestionOptionDto).filter(Objects::nonNull).collect(Collectors.toList());
        List<QdesQuestionDto.QdesCascaderOptionDto> optionList = question.getOptionListList().stream().map(this::toQdesCascaderOptionDto).filter(Objects::nonNull).collect(Collectors.toList());
        questionDto.setItems(items);
        questionDto.setRowItems(rowItems);
        questionDto.setOptionList(optionList);
        return questionDto;
    }

    private QdesQuestionDto.QdesCascaderOptionDto toQdesCascaderOptionDto(CascaderOption option) {
        if (option == null) {
            return null;
        }

        QdesQuestionDto.QdesCascaderOptionDto optionDto = new QdesQuestionDto.QdesCascaderOptionDto();
        optionDto.setGid(option.getGid());
        optionDto.setTitle(option.getTitle());
        optionDto.setPid(option.getPid());
        optionDto.setOoid(option.getOoid());
        return optionDto;
    }

    private QdesQuestionDto.QdesQuestionOptionDto toQdesQuestionOptionDto(QuestionOption option) {
        if (option == null) {
            return null;
        }

        QdesQuestionDto.QdesQuestionOptionDto optionDto = new QdesQuestionDto.QdesQuestionOptionDto();
        optionDto.setGid(option.getGid());
        optionDto.setTitle(option.getTitle());
        return optionDto;
    }

    //public List<ProjectExtraAttr> listProjectextraattr(String pid) {
    //    ListProjectExtraAttrRequest.Builder builder = ListProjectExtraAttrRequest.newBuilder();
    //    ProjectExtraAttr.Builder attr = ProjectExtraAttr.newBuilder();
    //    attr.setProjectId(pid);
    //    builder.setProjectExtraAttr(attr);
    //    ProjectExtraAttrSearchResponse response = baseQdesServiceBlockingStub.listProjectExtraAttr(builder.build());
    //    if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
    //        log.error("[Survey] listProjectextraattr, id = {} Error; ErrorMsg: {}", pid, response);
    //        return Collections.emptyList();
    //    }
    //    return response.getProjectExtraAttrListList();
    //}

    public List<QStruct> qdesListQstructWithq(String pid, Object version) {
        QStructSearchDataResquest.Builder builder = QStructSearchDataResquest.newBuilder();
        QStruct.Builder qStructBuilder = QStruct.newBuilder();
        qStructBuilder.setProjectId(pid);

        if (version instanceof Integer) {
            qStructBuilder.setVersion((Integer) version);
        }

        if (version instanceof List) {
            builder.addAllVersion(Convert.toList(Integer.class, version));
        }

        builder.setQstruct(qStructBuilder);
        QStructSearchDataResponse response = baseQdesServiceBlockingStub.qdesListQstructWithq(builder.build());
        if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
            log.error("[Survey] qdesListQstructWithq, id = {} Error; ErrorMsg: {}", pid, response);
            return Collections.emptyList();
        }
        return response.getQstructListList();
    }

    //public List<TranslationLanguage> listTranslationlanguage(String id, String language_code) {
    //    ListTranslationLanguageRequest.Builder builder = ListTranslationLanguageRequest.newBuilder();
    //    TranslationLanguage.Builder language = TranslationLanguage.newBuilder();
    //    language.setProjectId(id);
    //    language.setCode(language_code);
    //    builder.setTranslationLanguage(language.build());
    //    TranslationLanguageSearchResponse response = baseQdesServiceBlockingStub.listTranslationLanguage(builder.build());
    //    if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
    //        log.error("[Survey] listTranslationlanguage, projectId: {}, language_code: {},  response: {}", id, language_code, response);
    //        return Collections.emptyList();
    //    }
    //    return response.getTranslationLanguageListList();
    //}

    public List<QstructsDto> listQStruct(String projectId, Integer version) {
        ListQStructRequest.Builder builder = ListQStructRequest.newBuilder();
        QStruct qStruct = QStruct.newBuilder().setProjectId(projectId).setVersion(version).build();
        builder.setQStruct(qStruct);
        QStructSearchResponse response = baseQdesServiceBlockingStub.listQStruct(builder.build());
        if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
            log.error("[Survey] listQStruct failed, response: {}", response);
            return null;
        }
        return response.getQStructListList().stream().map(grpcConvertMapper::toQstructsDto)
                .collect(Collectors.toList());
    }

    public List<ProjectExtraAttr> listProjectExtraAttr(String id, String projectId) {
        ListProjectExtraAttrRequest.Builder builder = ListProjectExtraAttrRequest.newBuilder();
        ProjectExtraAttr.Builder projectExtraAttr = ProjectExtraAttr.newBuilder();
        if (StrUtil.isNotEmpty(id)) {
            projectExtraAttr.setId(id);
        }
        projectExtraAttr.setProjectId(projectId);
        builder.setProjectExtraAttr(projectExtraAttr.build());
        ProjectExtraAttrSearchResponse response = baseQdesServiceBlockingStub.listProjectExtraAttr(builder.build());
        if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
            log.error("[Survey] listProjectextraattr failed, response: {}", response);
            return null;
        }
        return response.getProjectExtraAttrListList();
    }

    public List<QdesNameListDto> listNameList(String project_id, int version, int gid) {
        try {
            ListNameListRequest.Builder builder = ListNameListRequest.newBuilder();
            NameList obj = NameList.newBuilder()
                    .setProjectId(project_id)
                    .setVersion(version)
                    .setGid(gid)
                    .build();
            builder.setNameList(obj);
            NameListSearchResponse response = baseQdesServiceBlockingStub.listNameList(builder.build());
            if (response.getStatus().getCodeValue() != Constants.SUCCESS) {
                log.error("[Survey] listNameList failed, response: {}", response);
                return null;
            }
            return response.getNameListListList().stream().map(grpcConvertMapper::toQdesNameListDto)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("[Survey] exp listNameList  ErrorMsg", e);
            return null;
        }
    }

    //public List<String> getProjectIds(String orgId) {
    //    GetProjectIdListRequest.Builder builder = GetProjectIdListRequest.newBuilder();
    //    builder.setOrgId(orgId);
    //    try {
    //        GetProjectIdListResponse response = baseQdesServiceBlockingStub.getProjectIdList(builder.build());
    //        if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
    //            log.error("[Survey] getProjectIds, orgId = {} Error; ErrorMsg: {}", orgId, response);
    //            return new ArrayList<>();
    //        }
    //        return new ArrayList<>(response.getProjectIdListList());
    //    } catch (Exception e) {
    //        log.error("[Survey] exp getProjectIds, orgId = {} Error;", orgId, e);
    //        return new ArrayList<>();
    //    }
    //}

    public List<String> qdesDistinctProjectIds(String customAttr) {
        Project.Builder builder = Project.newBuilder();
        builder.setCustomAttr(customAttr);
        Project project = builder.build();
        QdesDistinctProjectIdsResquest.Builder resquest = QdesDistinctProjectIdsResquest.newBuilder();
        resquest.setProject(project);
        try {
            QdesDistinctProjectIdsResponse response = baseQdesServiceBlockingStub.qdesDistinctProjectIds(resquest.build());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[Survey] qdesDistinctProjectIds, params = {} Error; ErrorMsg: {}", project, response);
                return new ArrayList<>();
            }
            return new ArrayList<>(response.getProjectIdListList());
        } catch (Exception e) {
            log.error("[Survey] exp qdesDistinctProjectIds, params = {} Error;", project, e);
            return new ArrayList<>();
        }
    }
}
